﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;
using System.Text;
using System.Diagnostics;
using Microsoft.Phone.Shell;
using System.Threading;

namespace WPKeyboard
{
    public partial class MainPage : PhoneApplicationPage
    {
        AppSettings settings;


        public MainPage()
        {
            InitializeComponent();

            settings = new AppSettings();

            TextBrush = new SolidColorBrush((Color)this.Resources["PhoneForegroundColor"]);
            AccentBrush = new SolidColorBrush((Color)this.Resources["PhoneAccentColor"]);
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
            this.OrientationChanged += new EventHandler<OrientationChangedEventArgs>(MainPage_OrientationChanged);
        }

        void MainPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
        {

        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {

            KeyboardLanguages = KeyboardInfoUtilities.GetCheckedLanguagesKeys();
            SetLanguage();

            string x = (App.Current as App).TextBlockText;
            if (!string.IsNullOrEmpty(x))
            {
                foreach (char c in x)
                {
                    // Right to left support
                    if (currentLanguageDirection == LanguageTextDirection.RightToLeft)
                    {
                        textBlock.Text.Reverse<char>();
                    }
                    
                    textBlock.Inlines.Add(new Run() { Text = c.ToString() });

                    // Right to left support
                    if (currentLanguageDirection == LanguageTextDirection.RightToLeft)
                    {
                        textBlock.Text.Reverse<char>();
                    }
                }

                
                TextIndex = textBlock.Text.Length;
            }

            phoneNumberChooserTask.Completed += new EventHandler<PhoneNumberResult>(PhoneNumberChooserTask_Completed);
            emailAddressChooserTask.Completed += new EventHandler<EmailResult>(EmailAddressChooserTask_Completed);
        }

        EmailAddressChooserTask emailAddressChooserTask = new EmailAddressChooserTask();
        PhoneNumberChooserTask phoneNumberChooserTask = new PhoneNumberChooserTask();

        List<string> KeyboardLanguages;
        int currentLanguageIndex = 1;
        public LanguageTextDirection currentLanguageDirection { get; set; }

        public string TextBlockText
        {
            get
            {
                return textBlock.Text;
            }
            set
            {
                textBlock.Text = value;
            }
        }
        public int TextIndex { get; set; }

        KeyboardState keyboardState = KeyboardState.AlphabetUpperCase;


        public readonly string IsLetter = "IsLetter";
        public readonly string NumericButtonText = "&123";
        public readonly string AlphabetButtonText = "ABC";

        private readonly SolidColorBrush TextBrush;
        private readonly SolidColorBrush AccentBrush;

        private void button_MouseLeftButtonDown(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;
            if (button.Tag.ToString() == IsLetter)
            {
                rolloverBorder.Visibility = System.Windows.Visibility.Visible;
                rolloverBorder.Margin = new Thickness(button.Margin.Left -  button.BorderThickness.Left, button.Margin.Top - button.Height, 0, 0);
            }
        }

        private void delete_MouseEnter(object sender, MouseEventArgs e)
        {
            if (textBlock.Inlines.Count == 0)
            {
                return;
            }

            IsDeleteKeyDown = true;

            var timer = new System.Windows.Threading.DispatcherTimer();

            timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
            timer.Tick += delegate
            {
                if (IsDeleteKeyDown)
                {
                    MultiCharactersDelete();
                }
            };

            timer.Start();
        }

        private volatile bool IsDeleteKeyDown;

        private void MultiCharactersDelete()
        {
            var timer = new System.Windows.Threading.DispatcherTimer();

            timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
            timer.Tick += delegate
            {
                // If the delete button is still pressed and we have characters left on the text block, then keep deleting.
                if (IsDeleteKeyDown && textBlock.Inlines.Count > 0)
                {
                    // Simulate a delete press
                    ProcessKey(delete);
                }
                else
                {
                    // Stops the dispatcher
                    timer.Stop();
                }
            };

            timer.Start();
        }

        private string ClickedButtonID;

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            
            Button button = sender as Button;
            if (button == null)
                return;

            ClickedButtonID = button.Name;

            CheckRollover(button);
            
        }

        private void ProcessKey(Button button)
        {
            string buttonContent = button.Content as string;

            if (buttonContent == (string)space.Content) //space was hit
            {
                buttonContent = " ";
            }
            else if (button.Name == (string)caps.Name)//caps was hit
            {
                MakeCaps();
                return;
            }
            else if (buttonContent == (string)numeric.Content) //numeric was hit
            {
                if (keyboardState == KeyboardState.AlphabetUpperCase || keyboardState == KeyboardState.AlphabetLowerCase)
                {
                    keyboardState = KeyboardState.Numeric1;
                    ShowNumeric();
                    button.Content = AlphabetButtonText;
                }
                else if (keyboardState == KeyboardState.Numeric1 || keyboardState == KeyboardState.Numeric2)
                {
                    keyboardState = KeyboardState.AlphabetUpperCase;
                    SetLanguage();
                    button.Content = NumericButtonText;
                }

                return;
            }
            else if (button.Name == enter.Name)//enter was hit
            {
                buttonContent = Environment.NewLine;
            }
            else if (button.Name == delete.Name)//delete was hit
            {
                DeleteCharacter();

                // Play delete click sound
                if (settings.IsPlayClickSoundChecked)
                {
                    Helpers.PlaySound(Helpers.ClickEffect.CharacterEffect);
                }

                return;
            }
            else if (button.Name == language.Name)//change language
            {
                currentLanguageIndex += 1;
                SetLanguage();
                return;
            }

            // If language is Right to Left, then we add the characters to the start (reversed)
            if (currentLanguageDirection == LanguageTextDirection.RightToLeft)
            {
                TextIndex = 0;
            }
            
            // If ENTER button clicked, then temporarly sets the TextIndex as length for the text won't be reveresed.
            if (button.Name == enter.Name)
            {
                TextIndex = textBlock.Inlines.Count;
            }

            
            // Vibrate for every click
            if (settings.IsVibrationChecked)
            {
                Helpers.Vibrate(Helpers.VibrationMode.Medium);
            }

            // Play space bar sound
            if (settings.IsPlayClickSoundChecked)
            {
                if (button.Name == space.Name)
                {
                    Helpers.PlaySound(Helpers.ClickEffect.SpaceBarEffect);
                }
                else
                {
                    Helpers.PlaySound(Helpers.ClickEffect.CharacterEffect);
                }
            }

            textBlock.Inlines.Insert(TextIndex, (new Run() { Text = buttonContent}));

            TextIndex += 1;
        }

        private void CheckRollover(Button button)
        {
            
            if (button.Tag != null && button.Tag.ToString() == IsLetter)
            {
                rolloverTextBlock.Text = button.Content.ToString();
                rolloverBorder.Visibility = Visibility.Visible;
                rolloverBorder.Margin = new Thickness(button.Margin.Left -  button.BorderThickness.Left, button.Margin.Top - button.Height, 0, 0);
            }
        }

        private void Button_MouseLeave(object sender, MouseEventArgs e)
        {
            if (sender is Button)
            {
                if (ClickedButtonID != (e.OriginalSource as Button).Name)
                    return;
                this.rolloverBorder.Visibility = Visibility.Collapsed;
            }

            // Cancel the MultiCharactersDelete
            IsDeleteKeyDown = false;

            // Proccess key press
            ProcessKey(sender as Button);
        }

        private void keysGrid_MouseMove(object sender, MouseEventArgs e)
        {
            Button button = e.OriginalSource as Button;
            if (button is Button && (button as Button).Tag != null && (button as Button).Tag.ToString() == IsLetter)
            {
                ClickedButtonID = (e.OriginalSource as Button).Name;
                rolloverTextBlock.Text = (e.OriginalSource as Button).Content.ToString();
                rolloverBorder.Margin = new Thickness(button.Margin.Left -  button.BorderThickness.Left, button.Margin.Top - button.Height, 0, 0);
            }
            else
            {
                rolloverBorder.Visibility = System.Windows.Visibility.Collapsed;
            }
        }

        private void DeleteCharacter()
        {
            if (TextIndex > 0)
            {
                // TODO: need to the support for Right to Left
                textBlock.Inlines.RemoveAt(TextIndex - 1);
                if(TextIndex>0) TextIndex--;
                if (TextIndex == 0 && textBlock.Inlines.Count > 0)
                {
                    TextIndex++;
                }
            }
        }

        private void SetLanguage()
        {
            if (currentLanguageIndex >= KeyboardLanguages.Count)
                currentLanguageIndex = 0;

            foreach (UIElement uie in keysGrid.Children)
            {
                if (!(uie is Button))
                    continue;

                Button button = uie as Button;

                if ((string)button.Tag != IsLetter)
                    continue;

                (uie as Button).Content = keyboardState == KeyboardState.AlphabetUpperCase ? KeyboardInfoUtilities.Languages[KeyboardLanguages[currentLanguageIndex]][button.Name].Value
                    : KeyboardInfoUtilities.Languages[KeyboardLanguages[currentLanguageIndex]][button.Name].Value;
            }

            language.Content = KeyboardLanguages[currentLanguageIndex != KeyboardLanguages.Count - 1 ?
                currentLanguageIndex + 1 : 0];

            // Setting a property for the current text diretion that will be used for aligning and reversing in case we are in Right to Left mode
            currentLanguageDirection = KeyboardInfoUtilities.LanguagesProperties[KeyboardLanguages[currentLanguageIndex]].TextDirection;

            // Setting the text direction as the language direction
            textBlock.TextAlignment = (currentLanguageDirection == LanguageTextDirection.LeftToRight) ? TextAlignment.Left : TextAlignment.Right;

        }

        // Not needed, Deleted.
/*        private void MoveCursor(Button button)
        {
            if (button.Name == left.Name && TextIndex > 1)
            {
                TextIndex--;
            }
            else if (button.Name == right.Name && TextIndex < textBlock.Text.Length)
            {
                TextIndex++;
            }
        }*/

        private void MakeCaps()
        {
            if (keyboardState == KeyboardState.AlphabetUpperCase)
            {
                foreach (UIElement c in keysGrid.Children)
                {
                    Button button = c as Button;
                    if (button == null || button.Content.GetType() != typeof(string)) continue;

                    if ((string)button.Content == ":") button.Content = ";";
                    else if ((string)button.Tag == IsLetter)
                        button.Content = KeyboardInfoUtilities.Languages[KeyboardLanguages[currentLanguageIndex]][button.Name].Value;
                }
                keyboardState = KeyboardState.AlphabetLowerCase;
            }
            else if (keyboardState == KeyboardState.AlphabetLowerCase)
            {
                foreach (UIElement c in keysGrid.Children)
                {
                    Button button = c as Button;
                    if (button == null || button.Content.GetType() != typeof(string)) continue;

                    if ((string)button.Content == ":") button.Content = ";";
                    else if ((string)button.Tag == IsLetter)
                        button.Content = KeyboardInfoUtilities.Languages[KeyboardLanguages[currentLanguageIndex]][button.Name].Caps;
                }
                keyboardState = KeyboardState.AlphabetUpperCase;

            }
            else if (keyboardState == KeyboardState.Numeric1 || keyboardState == KeyboardState.Numeric2)
            {
                ShowNumeric();
            }

        }

        private void ApplicationBarIconButtonSMS_Click(object sender, EventArgs e)
        {
            
            
            phoneNumberChooserTask.Show();
        }

        void PhoneNumberChooserTask_Completed(object sender, PhoneNumberResult e)
        {
            if (e.Error == null)
            {
                char[] arr = textBlock.Text.ToCharArray();

                // Check if the language is Right To Left
                if (currentLanguageDirection == LanguageTextDirection.RightToLeft)
                {
                    arr = arr.Reverse<char>().ToArray<char>(); 
                }
                
                string strTemp = new string(arr);

                if (e.TaskResult == TaskResult.OK)
                    Helpers.ShowSMSDialog(strTemp, e.PhoneNumber);
                else
                    Helpers.ShowSMSDialog(strTemp, string.Empty);
            }
        }

        

        private void ApplicationBarIconButtonEmail_Click(object sender, EventArgs e)
        {

            emailAddressChooserTask.Show();
        }

        void EmailAddressChooserTask_Completed(object sender, EmailResult e)
        {
            if (e.Error == null)
            {
                char[] arr = textBlock.Text.ToCharArray();

                // Check if the language is Right To Left
                if (currentLanguageDirection == LanguageTextDirection.RightToLeft)
                {
                    arr = arr.Reverse<char>().ToArray<char>(); 
                }
                
                string strTemp = new string(arr);
                
                
                if (e.TaskResult == TaskResult.OK)
                    Helpers.ShowEmailDialog(strTemp, e.Email);
                else
                    Helpers.ShowEmailDialog(strTemp, string.Empty);

            }
        }


        private void ApplicationBarIconButtonGoogle_Click(object sender, EventArgs e)
        {
            WebBrowserTask task = new WebBrowserTask();

            char[] arr = textBlock.Text.ToCharArray();

            // Check if the language is Right To Left
            if (currentLanguageDirection == LanguageTextDirection.RightToLeft)
            {
                arr = arr.Reverse<char>().ToArray<char>();
            }

            string strTemp = new string(arr);

            task.URL = @"http://www.google.gr?q=" + Uri.EscapeDataString(HttpUtility.UrlEncode(strTemp));
            task.Show();
        }

        private void ApplicationBarIconButtonBing_Click(object sender, EventArgs e)
        {
            WebBrowserTask task = new WebBrowserTask();

            char[] arr = textBlock.Text.ToCharArray();

            // Check if the language is Right To Left
            if (currentLanguageDirection == LanguageTextDirection.RightToLeft)
            {
                arr = arr.Reverse<char>().ToArray<char>();
            }
            string strTemp = new string(arr);

            task.URL = string.Format(@"http://m.bing.com/search/search.aspx?q={0}&go=&d=&dl=&pq=&a=results&MID=1", Uri.EscapeDataString(HttpUtility.UrlEncode(strTemp)));
            task.Show();
        }





        private void ShowNumeric()
        {
            if (keyboardState == KeyboardState.Numeric1)
            {
                foreach (UIElement c in keysGrid.Children)
                {
                    Button button = c as Button;
                    if (button == null || button.Content.GetType() != typeof(string)) continue;
                    else if ((string)button.Tag == IsLetter)
                        button.Content = KeyboardInfoUtilities.SpecialCharacters[button.Name].Value;
                }

                keyboardState = KeyboardState.Numeric2;
            }
            else if (keyboardState == KeyboardState.Numeric2)
            {
                foreach (UIElement c in keysGrid.Children)
                {
                    Button button = c as Button;
                    if (button == null || button.Content.GetType() != typeof(string)) continue;
                    else if ((string)button.Tag == IsLetter)
                        button.Content = KeyboardInfoUtilities.SpecialCharacters[button.Name].Caps;
                }

                keyboardState = KeyboardState.Numeric1;
            }
        }

        private void aboutMnu_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/About.xaml", UriKind.Relative));
        }

        private void settingsMnu_Click(object sender, EventArgs e)
        {
            // Navigate to the settings page
            NavigationService.Navigate(new Uri("/Settings.xaml", UriKind.Relative));
        }
    }

    public enum KeyboardState
    {

        AlphabetLowerCase,
        AlphabetUpperCase,
        Numeric1,
        Numeric2

    }

}
